package ipcc

import (
	"encoding/json"
	"i-hea/utils/httplib"
	"strings"

	log "github.com/astaxie/beego/logs"
	"github.com/pkg/errors"
)

var (
	callHost   string = "http://ccc.qcloud.com"
	httpClient *httplib.HttpClient
)

const (
	CallResultFailed       = iota // 呼叫失败
	CallResultRing                // 响铃
	CallResultAccept              // 接听
	CallResultBusy                // 用户忙
	CallResultUnknown             // 未知状态
	CallResultOutOfService        // 不在服务区
	CallResultStopService         // 停机
	CallResultReject              // 拒接
	CallResultPowerOff            // 关机
	CallResultInvalid             // 空号
	CallResultLimited             // 限制呼叫
	CallResultLineErr             // 线路错误
	CallResultNotAnswer           // 未接听
)

type MultyPlay struct {
	Voice     string
	VoiceType int //default is file "1" for tts
	Data      string
}

func OutCall(appid, number string, caller string) (string, error) {
	url := callHost + "/ipcc/call/outCall"

	param := outCallInfo{
		AppId:   appid,
		Caller:  caller,
		Called:  number,
		Data:    "testCallOut",
		Timeout: 40,
		AiFlag:  1,
	}

	log.Debug("appid:[%v] caller[%v] number[%v] start", appid, caller, number)

	jsonReq, _ := json.Marshal(param)

	resbody, err := httpClient.Post(url, jsonReq)
	if nil != err {
		log.Debug("new Call failed", err)
		return "", errors.Errorf("post return failed %v", err)
	}
	log.Debug(string(resbody))

	var result rspon
	json.Unmarshal(resbody, &result)

	return result.Callid, nil
}

func MultyPlays(appid, callid, data string, args []MultyPlay) bool {

	var orders []playInfo

	for _, v := range args {

		order := playInfo{
			Appid:     appid,
			CallId:    callid,
			GetKey:    0,
			Voice:     v.Voice,
			PlayTime:  1,
			MaxKey:    1,
			Key2End:   "#",
			TotalTime: 30,
			SpaceTime: 0,
			Data:      data,
			KeyStop:   1,
		}

		if v.VoiceType == 0 {
			order.Flag = 1
		} else if order.Flag == 1 {
			order.Flag = 0
		}

		orders = append(orders, order)
	}

	req := multyInfo{
		Appid:    appid,
		Callid:   callid,
		PlayTime: 1,
		Orders:   orders,
	}

	jsonReq, _ := json.Marshal(req)
	log.Debug("multy orders:", string(jsonReq))
	resbody, err := httpClient.Post(callHost+"/ipcc/call/multOrders", jsonReq)
	if nil != err {
		log.Error("post failed", err)
		return false
	}

	var rsp rspon
	err = json.Unmarshal(resbody, &rsp)
	if err != nil {
		log.Error("wrong msg:%v:%v, code is %v", string(resbody), err, rsp.Code)
		return false
	}

	return true
}

func PlayFile(appid, callid, file, data string) bool {
	play := playInfo{
		appid,
		callid,
		0, //1为获取DTMF
		1, //0为播放TTS
		file,
		1,   //播放次数
		0,   //最大获取按键数
		"#", //按键停止
		0,   //按键间隔
		30,  //总按键时长
		data,
		1,
	}

	jsonReq, _ := json.Marshal(play)
	log.Debug("play:", string(jsonReq))
	resbody, err := httpClient.Post(callHost+"/ipcc/call/play", jsonReq)
	if nil != err {
		log.Error("post failed", err)
		return false
	}

	var rsp rspon
	err = json.Unmarshal(resbody, &rsp)
	if err != nil {
		log.Error("wrong msg:%v:%v, code is %v", string(resbody), err, rsp.Code)
		return false
	}

	return true
}

func PlayTTS(appid, callid, text, data string) bool {

	play := playInfo{
		Appid:    appid,
		CallId:   callid,
		GetKey:   0, //1为获取DTMF
		Flag:     0, //0为播放TTS
		Voice:    text,
		PlayTime: 1, //播放次数
		Data:     data,
	}

	jsonReq, _ := json.Marshal(play)
	log.Debug("play:", string(jsonReq))
	resbody, err := httpClient.Post(callHost+"/ipcc/call/play", jsonReq)
	if nil != err {
		log.Error("post failed", err)
		return false
	}

	var rsp rspon
	err = json.Unmarshal(resbody, &rsp)
	if err != nil {
		log.Error("wrong msg:%v:%v, code is %v", string(resbody), err, rsp.Code)
		return false
	}

	return true
}

func StopPlay(appid, callid, data string) bool {

	stop := stopPlay{
		AppId:  appid,
		CallId: callid,
		Data:   data,
	}

	jsonReq, _ := json.Marshal(stop)
	resbody, err := httpClient.Post(callHost+"/ipcc/call/stoPlay", jsonReq)
	if nil != err {
		log.Error("post failed", err)
		return false
	}

	var rsp rspon
	err = json.Unmarshal(resbody, &rsp)
	if err != nil {
		log.Error("wrong msg:", string(resbody), err)
		return false
	}

	log.Debug("stop play result:%v", string(resbody))

	return strings.HasPrefix(rsp.Code, "0")
}

func HangUp(appId, callId string) {

	hung := hungupInfo{
		AppId:  appId,
		CallId: callId,
	}

	jsonReq, _ := json.Marshal(hung)
	resbody, err := httpClient.Post(callHost+"/ipcc/call/disConnect", jsonReq)
	if nil != err {
		log.Error("post failed", err)
		return
	}

	var rsp rspon
	err = json.Unmarshal(resbody, &rsp)
	if err != nil {
		log.Error("wrong msg:", string(resbody), err)
	}
}

func Init(host string) {

	callHost = host
	httpClient = httplib.NewHttpClient()
}

func StatusConvert(status int) (result string) {
	switch status {
	case CallResultFailed:
		result = "FAILED"
	case CallResultRing:
		result = "RING"
	case CallResultAccept:
		result = "ACCEPT"
	case CallResultBusy:
		result = "BUSY"
	case CallResultUnknown:
		result = "LINEERR"
	case CallResultOutOfService:
		result = "OUTOFSERVICE"
	case CallResultStopService:
		result = "STOPSERVICE"
	case CallResultReject:
		result = "REJECT"
	case CallResultPowerOff:
		result = "POWEROFF"
	case CallResultInvalid:
		result = "INVALID"
	case CallResultLimited:
		result = "LIMITED"
	case CallResultLineErr:
		result = "LINEERR"
	case CallResultNotAnswer:
		result = "NOTANSWER"
	default:
		result = "LINEERR"
	}

	return
}

func Reply(appid, callid string, accept bool) bool {

	request := replyInfo{
		AppId:   appid,
		CallId:  callid,
		AnsCode: 0,
		AiFlag:  1,
	}

	if false == accept {
		request.AnsCode = 1
	}

	jsonReq, _ := json.Marshal(request)
	resbody, err := httpClient.Post(callHost+"/ipcc/call/reply", jsonReq)
	if nil != err {
		log.Error("post failed", err)
		return false
	}

	var rsp rspon
	err = json.Unmarshal(resbody, &rsp)
	if err != nil {
		log.Error("[%v]wrong msg:", callid, string(resbody), err)
		return false
	}

	if strings.HasPrefix(rsp.Code, "0") {
		log.Error("[%v]wrong status:", callid, string(resbody))
		return false
	}

	return true
}

func CallNotify(call CallNotifyV2Info) (string, error) {

	jsonReq, _ := json.Marshal(call)
	resbody, err := httpClient.Post(callHost+"/ipcc/call/callNotifyV2", jsonReq)
	if nil != err {
		log.Error("post failed", err)
		return "", err
	}

	var result rspon
	json.Unmarshal(resbody, &result)

	return result.Callid, nil

}

func Transfer(appid, callid, caller, number string) (string, error) {
	request := TransferInfo{
		AppId:  appid,
		CallId: callid,
		Caller: caller,
		Called: number,
	}
	jsonReq, _ := json.Marshal(request)
	resbody, err := httpClient.Post(callHost+"/ipcc/v2/call/transfer", jsonReq)
	if nil != err {
		log.Error("post failed", err)
		return "", err
	}

	var result rspon
	json.Unmarshal(resbody, &result)

	return result.Callid, nil
}

func CallBack(request CallBackInfo) (string, error) {

	jsonReq, _ := json.Marshal(request)
	resbody, err := httpClient.Post(callHost+"/ipcc/call/callBack", jsonReq)
	if nil != err {
		log.Error("post failed", err)
		return "", err
	}

	var result rspon
	json.Unmarshal(resbody, &result)

	return result.Callid, nil
}

func CallBackPreCustomer(request CallBackInfo) (callid string, err error) {
	jsonReq, _ := json.Marshal(request)
	resbody, err := httpClient.Post(callHost+"/ipcc/call/callBackCustormer", jsonReq)
	if err != nil {
		return
	}

	var result rspon
	err = json.Unmarshal(resbody, &result)
	if err != nil {
		return
	}

	return result.Callid, nil
}

func ServiceMonitorTheCall(appid, callid, number string) (string, error) {
	request := ThreeWayCallSip{
		AppId:  appid,
		CallId: callid,
		Number: number,
	}

	jsonReq, _ := json.Marshal(request)
	resbody, err := httpClient.Post(callHost+"/ipcc/call/listenTheCall", jsonReq)
	if nil != err {
		log.Error("post failed", err)
		return "", err
	}

	var result rspon
	json.Unmarshal(resbody, &result)

	return result.Callid, nil
}

func ServiceReplaceTheCall(appid, callid string) (string, error) {

	request := MonitorInfo{
		AppId:  appid,
		CallId: callid,
	}

	jsonReq, _ := json.Marshal(request)
	resbody, err := httpClient.Post(callHost+"/ipcc/call/replaceTheCall", jsonReq)
	if nil != err {
		log.Error("post failed", err)
		return "", err
	}

	var result rspon
	json.Unmarshal(resbody, &result)

	return result.Callid, nil
}

func ServiceStopListen(appid, callid string) error {

	request := MonitorInfo{
		AppId:  appid,
		CallId: callid,
	}

	jsonReq, _ := json.Marshal(request)
	resbody, err := httpClient.Post(callHost+"/ipcc/call/stopListen", jsonReq)
	if nil != err {
		log.Error("post failed", err)
		return err
	}

	var result rspon
	json.Unmarshal(resbody, &result)

	/*
		if result.Code != "000000"{
			return  errors.Errorf("ipcc return:%v",result.Code)
		}*/

	return nil
}
